package top.dreamlove.core.ThreadDown;

import top.dreamlove.constant.Constant;
import top.dreamlove.utils.HttpUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.concurrent.*;

public class Download {
    public ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

    //线程池
    public ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(Constant.coreNumber,Constant.coreNumber,2,TimeUnit.MINUTES,new ArrayBlockingQueue<>(3));

    public CountDownLatch countDownLatch = new CountDownLatch(Constant.coreNumber);
    public void download(String url)  {

        if(url == null) return;
        HttpURLConnection httpURLConnection = null;
        try {
            //连接对象
            httpURLConnection = HttpUtils.getHttpURLConnection(url);

            //下载进度监控 获取文件大小并赋值
            DownloadInfoThreadShowInfo runnable =  new DownloadInfoThreadShowInfo(httpURLConnection.getContentLength());
            //创建执行器?
            scheduledExecutorService.scheduleAtFixedRate(runnable,1,1, TimeUnit.SECONDS);//循环查询进度

            //开始批量下载
            //1.创建多线程任务并分割指派给多个线程
            // ArrayList<Future> futureArrayList = split(url);
            split(url);

            //2.等待线程执行
            countDownLatch.await();

            // //2.获取结果,同时阻塞
            // futureArrayList.forEach((future) -> {
            //     try {
            //         //阻塞运行结果
            //         future.get();
            //     } catch (InterruptedException e) {
            //         throw new RuntimeException(e);
            //     } catch (ExecutionException e) {
            //         throw new RuntimeException(e);
            //     }
            // });



            //开始文件合并
            //获取文件名
            String httpFileName = HttpUtils.getHttpFileName(url);
            //文件下载路径
            httpFileName = Constant.Path + httpFileName;
            if(merge(httpFileName)){
                //清理临时文件
                cleanTempFile(httpFileName);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if(httpURLConnection != null){
                httpURLConnection.disconnect();
            }
            System.out.print("\r");
            System.out.print("下载完成");
            scheduledExecutorService.shutdownNow();
            poolExecutor.shutdownNow();
        }
    }

    //文件切分
    public ArrayList<Future> split(String url) throws IOException {
        long fileSize = HttpUtils.getHttpURLContentLength(url);//获取文件大小
        System.out.println("文件大小" + fileSize);



        long size = fileSize / Constant.splitNumber;//每一片的大小

        ArrayList<Future> futuresList = new ArrayList<>();

        //创建分块链接
        for (int i = 0; i < Constant.splitNumber; i++) {
            long start = i * size;
            long end;

            if(i != (Constant.splitNumber-1)){
                end = start + size;
            }else{
                end = 0;//结尾
            }
            //如果不是第一块,起始位置需要+1,比如第二块开始的起点应该是第一块结尾的区间 + 1,然后这里就用size代替了第一块的结尾区间,由于的平均的,所有第几块就乘几
            if(start != 0){
                start++;
            }
            //创建线程任务
            DownloadCallable downloadCallable = new DownloadCallable(url, start, end, i,countDownLatch);
            Future submit = poolExecutor.submit(downloadCallable);
            //返回结果存储
            futuresList.add(submit);
        }

        return futuresList;
    }

    //文件合并
    public boolean merge(String fileName){
        System.out.print("\r");
        System.out.print("开始合并文件");
        byte[] bytes = new byte[1024 * 8];
        int len = -1;
        try(RandomAccessFile accessFile = new RandomAccessFile(fileName,"rw")) {
            for (int i = 0; i < Constant.splitNumber; i++) {
                try( BufferedInputStream bop = new BufferedInputStream(new FileInputStream(fileName + Constant.prefix + i))){
                    while ((len = bop.read(bytes)) != -1){
                        accessFile.write(bytes,0,len);
                    }
                }
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    //临时文件清理
    public boolean cleanTempFile(String fileName){
        for (int i = 0; i < Constant.splitNumber; i++) {
            File file = new File(fileName + Constant.prefix + i);
            file.delete();
        }
        return true;
    }
}
